/*MyPhotoIndex Free Photo Organizer <www.myphotoindex.com>
  Copyright (C) <2006-2009>  <Asaf Yarkoni asaf@yarkoni.net>

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using MyPhotoIndex.Utilities;
using MyPhotoIndex.Interfaces;

namespace MyPhotoIndex.Controls
{
    public partial class MyPhotoIndexThumbnailViewer
    {
        private ThumbnailIcon m_lastMouseOnIcon;

        private void PhotoThumbViewer_MouseClick(object sender, MouseEventArgs e)
        {
            Thumbnail newSelectedImage = null;
            foreach (Thumbnail image in m_drawnImages)
            {
                if (image.FrameDrawingRect.Contains(e.Location))
                {
                    newSelectedImage = image;
                    break;
                }
            }

            if (newSelectedImage == null)
            {
                return;
            }

            ThumbnailIcon currentIcon = newSelectedImage.GetThumbnailIconFromMousePos(e.Location);
            if (currentIcon != ThumbnailIcon.Invalid)
            {
                if (currentIcon == ThumbnailIcon.CheckBox)
                {
                    ToggleChecked(newSelectedImage.ImageId);
                }

                if (ThumbnailMouseClickEvent != null)
                {
                    ThumbnailMouseClickEvent.Invoke(newSelectedImage, new ThumbnailMouseEventArgs(newSelectedImage.ImageId, e.Button, Control.ModifierKeys, e.X, e.Y, currentIcon, newSelectedImage.ImageDrawingRect));
                }

                return;
            }

            PointF relativeClickLocation = new PointF();
            relativeClickLocation.X = (float)newSelectedImage.ImageDrawingRect.Width / (float)(e.Location.X - newSelectedImage.ImageDrawingRect.X);
            relativeClickLocation.Y = (float)newSelectedImage.ImageDrawingRect.Height / (float)(e.Location.Y - newSelectedImage.ImageDrawingRect.Y);

            bool selected = false;
            if (m_useSelection == true)
            {
                if ((Control.ModifierKeys & Keys.Control) != Keys.Control &&
                    (Control.ModifierKeys & Keys.Shift) != Keys.Shift)
                {
                    bool clearSelected = true;
                    if (e.Button == MouseButtons.Right &&
                        IsSelected(newSelectedImage.ImageId) == true)
                    {
                        clearSelected = false;
                    }

                    if (clearSelected)
                    {
                        ClearSelection();
                    }

                    selected = true;
                }
                else
                    if ((Control.ModifierKeys & Keys.Control) == Keys.Control)
                    {
                        selected = !IsSelected(newSelectedImage.ImageId);
                    }
                    else
                        if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift)
                        {
                            if (m_selectedImages.Count > 0)
                            {
                                int lastSelectedImageId = m_selectedImages[m_selectedImages.Count - 1];
                                int lastSelectedOffset = ImageIdToImageOffset(lastSelectedImageId);
                                int newSelectedOffset = ImageIdToImageOffset(newSelectedImage.ImageId);
                                int from = Math.Min(lastSelectedOffset, newSelectedOffset);
                                int to = Math.Max(lastSelectedOffset, newSelectedOffset);

                                for (int ii = from; ii <= to; ii++)
                                {
                                    int imageId = ImageOffsetToImageId(ii);
                                    if (IsSelected(imageId) == false)
                                    {
                                        m_selectedImages.Add(imageId);
                                    }
                                }

                                this.Invalidate();

                                if (SelectionChangedEvent != null)
                                {
                                    SelectedImageInfo lastSelected = new SelectedImageInfo(newSelectedImage.ImageId, selected ? SelectedImageSelectedState.Select : SelectedImageSelectedState.Unselect, SelectedImageSelectionMethod.Mouse, e.Location, relativeClickLocation);
                                    SelectionChangedEvent.Invoke(this, lastSelected);
                                }

                                return;
                            }
                        }
            }
            else
            {
                return;
            }

            if (m_singleSelection == true)
            {
                ClearSelection();
            }

            SelectedImageInfo lastSelectedImage = new SelectedImageInfo(newSelectedImage.ImageId, selected ? SelectedImageSelectedState.Select : SelectedImageSelectedState.Unselect, SelectedImageSelectionMethod.Mouse, e.Location, relativeClickLocation);
            SelectImage(newSelectedImage.ImageId, selected, lastSelectedImage);

            if (ThumbnailMouseClickEvent != null)
            {
                ThumbnailMouseClickEvent.Invoke(newSelectedImage, new ThumbnailMouseEventArgs(newSelectedImage.ImageId, e.Button, Control.ModifierKeys, e.X, e.Y, ThumbnailIcon.Invalid, newSelectedImage.ImageDrawingRect));
            }
        }

        void MyPhotoIndexThumbnailViewer_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            Thumbnail newSelectedImage = null;
            foreach (Thumbnail image in m_drawnImages)
            {
                if (image.FrameDrawingRect.Contains(e.Location))
                {
                    newSelectedImage = image;
                    break;
                }
            }

            if (newSelectedImage == null)
            {
                return;
            }

            ThumbnailIcon currentIcon = newSelectedImage.GetThumbnailIconFromMousePos(e.Location);
            if (ThumbnailIcon.Invalid == currentIcon)
            {
                if (ThumbnailMouseDoubleClickEvent != null)
                {
                    ThumbnailMouseDoubleClickEvent.Invoke(newSelectedImage, new ThumbnailMouseEventArgs(newSelectedImage.ImageId, e.Button, Control.ModifierKeys, e.X, e.Y, currentIcon, newSelectedImage.ImageDrawingRect));
                }

                return;
            }
        }

        void MyPhotoIndexThumbnailViewer_MouseMove(object sender, MouseEventArgs e)
        {
            Thumbnail newSelectedImage = null;
            foreach (Thumbnail image in m_drawnImages)
            {
                if (image != null && 
                    image.FrameDrawingRect.Contains(e.Location))
                {
                    newSelectedImage = image;
                    break;
                }
            }

            if (newSelectedImage == null)
            {
                if (ThumbnailIcon.Invalid != m_lastMouseOnIcon)
                {
                    if (ThumbnailIconMouseLeaveEvent != null)
                    {
                        ThumbnailIconMouseLeaveEvent.Invoke(this, new ThumbnailMouseEventArgs(-1, e.Button, Control.ModifierKeys, e.X, e.Y, m_lastMouseOnIcon, Rectangle.Empty));
                    }
                }

                m_lastMouseOnIcon = ThumbnailIcon.Invalid;

                return;
            }

            ThumbnailIcon currentIcon = newSelectedImage.GetThumbnailIconFromMousePos(e.Location);
            if (currentIcon != m_lastMouseOnIcon)
            {
                if (ThumbnailIcon.Invalid != m_lastMouseOnIcon)
                {
                    if (ThumbnailIconMouseLeaveEvent != null)
                    {
                        ThumbnailIconMouseLeaveEvent.Invoke(this, new ThumbnailMouseEventArgs(newSelectedImage.ImageId, e.Button, Control.ModifierKeys, e.X, e.Y, m_lastMouseOnIcon, newSelectedImage.ImageDrawingRect));
                    }
                }

                if (currentIcon != ThumbnailIcon.Invalid)
                {
                    if (ThumbnailIconMouseEnterEvent != null)
                    {
                        ThumbnailIconMouseEnterEvent.Invoke(this, new ThumbnailMouseEventArgs(newSelectedImage.ImageId, e.Button, Control.ModifierKeys, e.X, e.Y, currentIcon, newSelectedImage.ImageDrawingRect));
                    }
                }

                m_lastMouseOnIcon = currentIcon;
            }
        }



        private ImageList m_imageListDrag = new ImageList();
        private Rectangle m_dragBoxFromMouseDown;

        private void MyPhotoIndexThumbnailViewer_MouseMoveDrag(object sender, MouseEventArgs e)
        {
            if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
            {
                if (m_dragBoxFromMouseDown != Rectangle.Empty &&
                    !m_dragBoxFromMouseDown.Contains(e.X, e.Y))
                {
                    Thumbnail thumbnail = GetThumbnailFromPosition(this.PointToScreen(e.Location));
                    if (thumbnail == null)
                    {
                        return;
                    }

                    DragDropThumbnail(thumbnail, this.PointToScreen(e.Location));
                }
            }
        }

        void MyPhotoIndexThumbnailViewer_MouseDownDragDrop(object sender, MouseEventArgs e)
        {
            Thumbnail thumbnail = this.GetThumbnailFromPosition(this.PointToScreen(e.Location));
            if (thumbnail == null)
            {
                return;
            }

            bool isDragable = true;

            if (isDragable == true)
            {
                Size dragSize = new Size(SystemInformation.DragSize.Width + 5, SystemInformation.DragSize.Height + 5);
                m_dragBoxFromMouseDown = new Rectangle(new Point(e.X - (dragSize.Width / 2),
                                                               e.Y - (dragSize.Height / 2)), dragSize);
            }
            else
            {
                m_dragBoxFromMouseDown = Rectangle.Empty;
            }
        }

        void MyPhotoIndexThumbnailViewer_MouseUpDragDrop(object sender, MouseEventArgs e)
        {
            m_dragBoxFromMouseDown = Rectangle.Empty;
        }

        private void DragDropThumbnail(Thumbnail thumbnail, Point mousePosition)
        {
            if (m_allowDrag == false)
            {
                return;
            }

            // Reset image list used for drag image
            this.m_imageListDrag.Images.Clear();

            Image dragImage = thumbnail.ImageData.Thumbnail;
            thumbnail.ImageData.ThumbnailReferences++;
            thumbnail.ImageData.ThumbnailReferences--;

            SizeF requestedSize = new SizeF(Math.Min(thumbnail.ImageDrawingRect.Width, 256), Math.Min(thumbnail.ImageDrawingRect.Height, 256));
            SizeF origSize = new SizeF(thumbnail.ImageDrawingRect.Width, thumbnail.ImageDrawingRect.Height);
            Size dragSize = ImageAlgo.GetImageProportionalSize(origSize, requestedSize);

            this.m_imageListDrag.ImageSize = dragSize;

            if (dragImage == null)
            {
                dragImage = Resources.Resources.NoImage;
            }

            using (Bitmap bmp = new Bitmap(dragImage, dragSize.Width, dragSize.Height))
            {
                this.m_imageListDrag.Images.Add(bmp);

                Point p = this.PointToScreen(new Point(thumbnail.ImageDrawingRect.Left, thumbnail.ImageDrawingRect.Top));
                int xOffset = mousePosition.X - p.X - (int)((origSize.Width - requestedSize.Width) / 2);
                int yOffset = mousePosition.Y - p.Y - (int)((origSize.Height - requestedSize.Height) / 2);

                // Begin dragging image
                if (Win32Interop.ImageDragHelper.ImageList_BeginDrag(this.m_imageListDrag.Handle, 0, xOffset, yOffset))
                {
                    // Begin dragging
                    this.DoDragDrop(thumbnail, DragDropEffects.Link);
                    // End dragging image
                    Win32Interop.ImageDragHelper.ImageList_EndDrag();
                }
            }
        }
    }
}
